import axios, { AxiosRequestConfig } from 'axios';
import { message as $message, Modal } from 'ant-design-vue';
import { Storage } from '@/framework/utils/Storage';
import qs from 'qs';

export interface RequestOptions {
  /** 当前接口权限, 不需要鉴权的接口请忽略， 格式：sys:user:add */
  permCode?: string;
  /** 是否直接获取data，而忽略message等 */
  isGetDataDirectly?: boolean;
  /** 请求成功是提示信息 */
  successMsg?: string;
  /** 请求失败是提示信息 */
  errorMsg?: string;
  /** 是否mock数据请求 */
  isMock?: boolean;
}

const UNKNOWN_ERROR = '未知错误，请重试';

/** 真实请求的路径前缀 */
const baseApiUrl = import.meta.env.VITE_BASE_API;
/** mock请求路径前缀 */
const baseMockUrl = import.meta.env.VITE_MOCK_API;

const service = axios.create({
  baseURL: '',
  timeout: 12000,
});

service.interceptors.request.use(
  (config) => {
    // 针对get请求进行qs处理
    if (config.method === 'get' || config.method === 'GET') {
      if (config.params) {
        config.params = qs.stringify(config.params, { arrayFormat: 'indices', allowDots: true });
        config.params = decodeURI(config.params);
        var result = {};
        config.params.split('&').forEach((item) => {
          if (!item) return;
          let s = item.split('=');
          result[s[0]] = s[1].replace(/%2C/g, ',');
        });
        config.params = result;
      }
    }
    return config;
  },
  (error) => {
    Promise.reject(error);
  },
);

service.interceptors.response.use(
  (response) => {
    const res = response.data;

    // if the custom code is not 200, it is judged as an error.
    if (res.code && res.code !== 200) {
      $message.error(res.message || UNKNOWN_ERROR);
      if (res.code === 401) {
        // 401 会话超时清除token
        Storage.clear();
        Storage.removeCookie('token');
        let failData = res.data;
        if (failData) {
        }

        // 重新登录
        Modal.confirm({
          title: '警告',
          content: res.message || '账号异常，您可以取消停留在该页上，或重新登录',
          okText: '重新登录',
          cancelText: '取消',
          onOk: () => {
            Storage.removeCookie('token');
            localStorage.clear();
            window.location.reload();
          },
        });
      }

      // throw other
      const error = new Error(res.message || UNKNOWN_ERROR) as Error & { code: any };
      error.code = res.code;
      return Promise.reject(error);
    }
    // 兼容菌毒种
    else if (res.status && res.status !== 200) {
      $message.error(res.message || UNKNOWN_ERROR);
      if (res.status === 401) {
        // 401 会话超时清除token
        Storage.clear();
        Storage.removeCookie('token');
        let failData = res.data;
        if (failData) {
        }

        // 重新登录
        Modal.confirm({
          title: '警告',
          content: res.message || '账号异常，您可以取消停留在该页上，或重新登录',
          okText: '重新登录',
          cancelText: '取消',
          onOk: () => {
            Storage.removeCookie('token');
            localStorage.clear();
            window.location.reload();
          },
        });
      }

      // throw other
      const error = new Error(res.message || UNKNOWN_ERROR) as Error & { status: any };
      error.status = res.status;
      return Promise.reject(error);
    } else {
      return res;
    }
  },
  (error) => {
    // 处理 422 或者 500 的错误异常提示
    const errMsg = error?.response?.data?.message ?? UNKNOWN_ERROR;
    $message.error(errMsg);
    error.message = errMsg;
    return Promise.reject(error);
  },
);

export type Response<T = any> = {
  code: number;
  message: string;
  data: T;
  success: boolean;
};

export type BaseResponse<T = any> = Promise<Response<T>>;

/**
 *
 * @param method - request methods
 * @param url - request url
 * @param data - request data or params
 */
export const request = async <T = any>(config: AxiosRequestConfig, options: RequestOptions = {}): Promise<T> => {
  try {
    const { successMsg, errorMsg, isMock, isGetDataDirectly = true } = options;
    // const fullUrl = `${(isMock ? baseMockUrl : baseApiUrl) + config.url}`;
    config.baseURL ??= isMock ? baseMockUrl : baseApiUrl;
    config.url = config.url;

    const res = await service.request(config);
    successMsg && $message.success(successMsg);
    errorMsg && $message.error(errorMsg);
    return isGetDataDirectly ? res.data : res;
  } catch (error: any) {
    return Promise.reject(error);
  }
};
